home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / networking / misc / wu-ftpd-37.14.lha / wu-ftpd / src / amiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-11  |  8.8 KB  |  453 lines

  1. /*
  2.  * Amiga support routines for chroot() emulation
  3.  * © 1994 Blaz Zupan, <blaz.zupan@uni-mb.si>
  4.  * All Rights Reserved
  5.  *
  6.  * Contains:
  7.  *
  8.  *   chroot()
  9.  *   CheckAccess()
  10.  *   amiga_seteuid()
  11.  *   amiga_getuid()
  12.  *   amiga_getpwnam()
  13.  *   amiga_getgrnam()
  14.  *   amiga_umask()
  15.  *
  16.  */
  17.  
  18. #include <libraries/multiuser.h>
  19. #include <proto/multiuser.h>
  20. #include <proto/dos.h>
  21. #include <proto/usergroup.h>
  22. #include <string.h>
  23. #include <stdio.h>
  24. #include "extensions.h"
  25. #include "config.h"
  26.  
  27. extern char *amigausername;
  28. extern struct muBase *muBase;
  29.  
  30. /*
  31.  * This routine is an attempt to emulate the Unix chroot()
  32.  * function. It only saves the name supplied in the global
  33.  * AmigaRootDir. Everything else must be done by CheckAccess().
  34.  */
  35. extern int anonymous, guest;
  36. char AmigaRootDir[MAXPATHLEN + 2] = "";
  37.  
  38. int
  39. chroot (char *dir)
  40. {
  41.   BPTR lock;
  42.  
  43.   if (lock = Lock (dir, SHARED_LOCK))
  44.   {
  45.     NameFromLock (lock, AmigaRootDir, MAXPATHLEN);
  46.     UnLock (lock);
  47.     return 0;
  48.   }
  49.   return -1;
  50. }
  51.  
  52. /*
  53.  * Checks if pathname "name1" is above
  54.  * "name" in directory structure.
  55.  */
  56. static BOOL
  57. IsParent (char *name1, char *name2)
  58. {
  59.   BOOL ret = FALSE;
  60.   BPTR l1;
  61.  
  62.   if (l1 = Lock (name1, SHARED_LOCK))
  63.   {
  64.     BPTR l2;
  65.  
  66.     if (l2 = Lock (name2, SHARED_LOCK))
  67.     {
  68.       switch (SameLock (l1, l2))
  69.       {
  70.       case LOCK_DIFFERENT:
  71.     break;
  72.       case LOCK_SAME:
  73.     ret = TRUE;
  74.     break;
  75.       case LOCK_SAME_VOLUME:
  76.     {
  77.       BPTR l;
  78.  
  79.       while (l2)
  80.       {
  81.         l = l2;
  82.         l2 = ParentDir (l);
  83.         UnLock (l);
  84.         if (SameLock (l1, l2) == LOCK_SAME)
  85.         {
  86.           ret = TRUE;
  87.           break;
  88.         }
  89.       }
  90.       break;
  91.     }
  92.       }
  93.       UnLock (l2);
  94.     }
  95.     UnLock (l1);
  96.   }
  97.   return ret;
  98. }
  99.  
  100. /* Compare two strings with pattern matching */
  101. static BOOL
  102. mymatch (char *pattern, char *string)
  103. {
  104.   BOOL ret = FALSE;
  105.   char *parsedpattern;
  106.   long len = strlen (pattern) * 2 + 10;
  107.   long oldflags = DOSBase->dl_Root->rn_Flags;
  108.  
  109.   DOSBase->dl_Root->rn_Flags |= RNF_WILDSTAR;    /* turn on recognitions of star as wildcard */
  110.   if (parsedpattern = malloc (len))
  111.   {
  112.     if (ParsePattern (pattern, parsedpattern, len) != -1)
  113.       ret = MatchPattern (parsedpattern, string);
  114.     free (parsedpattern);
  115.   }
  116.   DOSBase->dl_Root->rn_Flags = oldflags;    /* restore original flags */
  117.   return ret;
  118. }
  119.  
  120. /* Checks if user is allowed to access file/directory.
  121.  * If create == TRUE check for parent of specified name
  122.  * (this is used if we want to check if user is allowed
  123.  * to access the directory into which a file should be
  124.  * created - so now "put <something> AmiTCP:db/passwd"
  125.  * hacks are possible).
  126.  */
  127. BOOL
  128. CheckAccess (char *dir, BOOL create)
  129. {
  130.   BPTR lock;
  131.   char name[MAXPATHLEN];
  132.   struct aclmember *entry = NULL;
  133.  
  134.   strcpy (name, dir);
  135.   lock = Lock (name, SHARED_LOCK);
  136.   if (!lock && create)
  137.   {
  138.     *(FilePart (name)) = 0;
  139.     lock = Lock (name, SHARED_LOCK);
  140.   }
  141.  
  142.   if (lock)
  143.     UnLock (lock);
  144.   else
  145.     /* If we could not access file/directory then return "OK"
  146.      * for now because access will be denied later by the
  147.      * command that called us.
  148.      */
  149.     return TRUE;
  150.  
  151.  
  152.   /* first check if directory is on "deny" list */
  153.   while (getaclentry ("denydir", &entry) && ARG0 && ARG1)
  154.   {
  155.     if (mymatch (ARG1, amigausername) && IsParent (ARG0, name))
  156.       return FALSE;
  157.   }
  158.   /* now see if it is under root dir */
  159.   if (IsParent (AmigaRootDir, name))
  160.     return TRUE;
  161.   /* check if access is allowed even if dir is not under root */
  162.   else
  163.   {
  164.     entry = NULL;
  165.     while (getaclentry ("allowdir", &entry) && ARG0 && ARG1)
  166.     {
  167.       if (mymatch (ARG1, amigausername) && IsParent (ARG0, name))
  168.     return TRUE;
  169.     }
  170.   }
  171.   /* If directory is not on deny or allow list and not
  172.    * under root directory then we allow access for
  173.    * real users and don't allow access for guests.
  174.    */
  175.   if (!anonymous && !guest)
  176.     return TRUE;
  177.   else
  178.     return FALSE;
  179. }
  180.  
  181. /*
  182.  * Simulate Unix geteuid() call with MultiUser.
  183.  */
  184. int
  185. amiga_geteuid (void)
  186. {
  187.   if (muBase)
  188.     return ((muGetTaskOwner (FindTask (NULL)) & muMASK_UID) >> 16);
  189.   else
  190. #undef geteuid
  191.     return (geteuid ());
  192. }
  193.  
  194. /*
  195.  * Simulate Unix seteuid() call with MultiUser.
  196.  * You have to be logged in as root initially for this
  197.  * routine to work (after that it correctly keeps track
  198.  * of the user).
  199.  */
  200. int
  201. amiga_seteuid (int u)
  202. {
  203.   if (muBase)
  204.   {
  205.     ULONG tags[5];
  206.     int res = -1;
  207.  
  208.     if (u == 0)
  209.     {
  210.       int uid;
  211.  
  212.       uid = amiga_geteuid ();
  213.  
  214.       /* Are we already root? */
  215.       if (uid == muROOT_UID)
  216.     return 0;
  217.  
  218.       /* We can't set effective user ID to root
  219.        * if we are currently logged in as nobody
  220.        */
  221.       if (uid == muNOBODY_UID)
  222.     return -1;
  223.  
  224.       /* Now logout until we become either root or
  225.        * nobody. If we become nobody we fail.
  226.        */
  227.       do
  228.       {
  229.     tags[0] = muT_Quiet;
  230.     tags[1] = TRUE;
  231.     tags[2] = TAG_END;
  232.     muLogoutA (tags);
  233.     uid = amiga_geteuid ();
  234.       }
  235.       while (uid != muROOT_UID && uid != muNOBODY_UID);
  236.  
  237.       return ((uid == muROOT_UID) ? 0 : -1);
  238.     }
  239.  
  240.     /* Check if we are maybe already logged in as that user. */
  241.     if (u == amiga_geteuid ())
  242.       return 0;
  243.  
  244.     /* Ok, so we are trying to login as someone else.
  245.      * first make sure that we are root. */
  246.     if (amiga_seteuid (0) != -1)
  247.     {
  248.       struct muUserInfo *ui;
  249.  
  250.       if (ui = muAllocUserInfo ())
  251.       {
  252.     ui->uid = u;
  253.     if (muGetUserInfo (ui, muKeyType_uid))
  254.     {
  255.       tags[0] = muT_UserID;
  256.       tags[1] = (ULONG) ui->UserID;
  257.       tags[2] = muT_NoLog;
  258.       tags[3] = TRUE;
  259.       tags[4] = TAG_END;
  260.       res = (muLoginA (tags) ? 0 : -1);
  261.     }
  262.     muFreeUserInfo (ui);
  263.       }
  264.     }
  265.     return res;
  266.   }
  267.   /* MultiUser is not installed so use dummy
  268.    * usergroup.library call.
  269.    */
  270. #undef seteuid
  271.   return (seteuid (u));
  272. }
  273.  
  274. /*
  275.  * Simulate Unix seteuid() call with MultiUser.
  276.  * You have to be logged in as root initially for this
  277.  * routine to work (after that it correctly keeps track
  278.  * of the user).
  279.  */
  280. int
  281. amiga_setegid (int g)
  282. {
  283.   /* We can't set another group under
  284.    * MultiUser so we fail.
  285.    */
  286.   if (muBase)
  287.     return -1;
  288.   /* MultiUser is not installed so use dummy
  289.    * usergroup.library call.
  290.    */
  291. #undef setegid
  292.   return (setegid (g));
  293. }
  294.  
  295.  
  296. /*
  297.  * Simulate Unix getpwnam() call with MultiUser.
  298.  */
  299.  
  300. static struct passwd p;
  301.  
  302. struct passwd *
  303. amiga_getpwnam (char *name)
  304. {
  305.   if (muBase)
  306.   {
  307.     struct muUserInfo *ui;
  308.     BOOL ok = FALSE;
  309.  
  310.     if (ui = muAllocUserInfo ())
  311.     {
  312.       strcpy (ui->UserID, name);
  313.       if (muGetUserInfo (ui, muKeyType_UserID))
  314.       {
  315.     p.pw_uid = ui->uid;
  316.     p.pw_gid = ui->gid;
  317.     if (p.pw_name)
  318.       free (p.pw_name);
  319.     p.pw_name = malloc (strlen (ui->UserID) + 1);
  320.     if (p.pw_name)
  321.       strcpy (p.pw_name, ui->UserID);
  322.     p.pw_passwd = NULL;
  323.     if (p.pw_gecos)
  324.       free (p.pw_gecos);
  325.     p.pw_gecos = malloc (strlen (ui->UserName) + 1);
  326.     if (p.pw_gecos)
  327.       strcpy (p.pw_gecos, ui->UserName);
  328.     if (p.pw_dir)
  329.       free (p.pw_dir);
  330.     p.pw_dir = malloc (strlen (ui->HomeDir) + 1);
  331.     if (p.pw_dir)
  332.       strcpy (p.pw_dir, ui->HomeDir);
  333.     if (p.pw_shell)
  334.       free (p.pw_shell);
  335.     p.pw_shell = malloc (strlen (ui->Shell) + 1);
  336.     if (p.pw_shell)
  337.       strcpy (p.pw_shell, ui->Shell);
  338.     ok = TRUE;
  339.       }
  340.       muFreeUserInfo (ui);
  341.     }
  342.     if (!ok)
  343.       return (NULL);
  344.     return (&p);
  345.   }
  346. #undef getpwnam
  347.   return (getpwnam (name));
  348. }
  349.  
  350. /*
  351.  * Simulate Unix getgrnam() call with MultiUser.
  352.  */
  353.  
  354. static struct group g;
  355.  
  356. struct group *
  357. amiga_getgrnam (char *name)
  358. {
  359.   if (muBase)
  360.   {
  361.     struct muGroupInfo *gi;
  362.     BOOL ok = FALSE;
  363.  
  364.     if (gi = muAllocGroupInfo ())
  365.     {
  366.       strcpy (gi->GroupID, name);
  367.       if (muGetGroupInfo (gi, muKeyType_GroupID))
  368.       {
  369.     static char *dummy_memb = NULL;
  370.  
  371.     g.gr_gid = gi->gid;
  372.     if (g.gr_name)
  373.       free (g.gr_name);
  374.     g.gr_name = malloc (strlen (gi->GroupID) + 1);
  375.     if (g.gr_name)
  376.       strcpy (g.gr_name, gi->GroupID);
  377.     g.gr_passwd = NULL;
  378.     g.gr_mem = &dummy_memb;;
  379.     ok = TRUE;
  380.       }
  381.       muFreeGroupInfo (gi);
  382.     }
  383.     if (!ok)
  384.       return (NULL);
  385.     return (&g);
  386.   }
  387. #undef getgrnam
  388.   return (getgrnam (name));
  389. }
  390.  
  391. /*
  392.  * Simulate Unix umask() call with MultiUser.
  393.  */
  394.  
  395. const static BYTE abits[8] =
  396. {
  397.   0, 0x2, 0x5, 0x7, 0x8, 0xA, 0xD, 0xF,
  398. };
  399.  
  400. const static BYTE ubits[16] =
  401. {
  402.   0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7
  403. };
  404.  
  405. ULONG
  406. U2A_prot (int mode)
  407. {
  408.   return ((abits[mode & 7] << FIBB_OTR_DELETE) |
  409.       (abits[(mode >> 3) & 7] << FIBB_GRP_DELETE) |
  410.       (abits[(mode >> 6) & 7] ^ 0xf));
  411. }
  412.  
  413. int
  414. A2U_prot (ULONG mode)
  415. {
  416.   return ((ubits[(mode >> 12) & 15] << 6) |
  417.       (ubits[(mode >> 8) & 15] << 3) |
  418.       (ubits[mode & 15]));
  419. }
  420.  
  421. int
  422. amiga_umask (int m)
  423. {
  424.   if (muBase)
  425.   {
  426.     ULONG tags[3];
  427.     ULONG oldmask;
  428.  
  429.     tags[0] = muT_DefProtection;
  430.     tags[1] = U2A_prot (m);
  431.     tags[2] = TAG_END;
  432.     oldmask = muGetDefProtection (NULL);
  433.     muSetDefProtection (tags);
  434.     return (A2U_prot (oldmask));
  435.   }
  436. #undef umask
  437.   return (umask (m));
  438. }
  439.  
  440. /* dummy stub function for compatibility with original source */
  441. FILE *
  442. ftpd_popen (char *program, char *type, int closestderr)
  443. {
  444.   return (popen (program, type));
  445. }
  446.  
  447. /* dummy stub function for compatibility with original source */
  448. void
  449. ftpd_pclose (FILE * iop)
  450. {
  451.   pclose (iop);
  452. }
  453.